// 文件上传配置模块
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { v4 as uuidv4 } from 'uuid';
import { ApiError } from '../middleware/errorHandler.js';

// 基础上传路径配置
const BASE_UPLOAD_PATH = process.env.UPLOAD_PATH || 'uploads';

// 确保上传目录存在
const ensureUploadDirExists = (dir) => {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  return dir;
};

// 创建存储引擎
const createStorage = (subDir) => {
  const uploadPath = path.join(BASE_UPLOAD_PATH, subDir);
  ensureUploadDirExists(uploadPath);
  
  return multer.diskStorage({
    destination: (req, file, cb) => {
      cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
      // 生成唯一文件名
      const uniqueFilename = `${Date.now()}-${uuidv4()}${path.extname(file.originalname)}`;
      cb(null, uniqueFilename);
    }
  });
};

// 文件过滤器
const fileFilter = (allowedTypes) => {
  return (req, file, cb) => {
    const mimeType = file.mimetype.toLowerCase();
    if (allowedTypes.includes(mimeType)) {
      cb(null, true);
    } else {
      cb(new ApiError(400, '不支持的文件类型'));
    }
  };
};

// 文件大小限制配置
const fileSizeLimits = {
  avatar: 2 * 1024 * 1024,       // 2MB 头像
  document: 10 * 1024 * 1024,    // 10MB 文档
  media: 500 * 1024 * 1024,      // 500MB 媒体文件
  chunk: 5 * 1024 * 1024         // 5MB 分块大小
};

// 文件类型配置
const fileTypes = {
  images: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
  documents: ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
  videos: ['video/mp4', 'video/mpeg', 'video/quicktime', 'video/x-msvideo'],
  audio: ['audio/mpeg', 'audio/wav', 'audio/ogg'],
  any: []  // 空数组表示接受所有类型
};

// 创建上传实例
const createUploader = (options) => {
  const { 
    subDir = 'default',  // 子目录
    fileType = 'any',    // 文件类型
    maxSize = fileSizeLimits.document,  // 默认文件大小限制
    maxCount = 1         // 默认单文件上传
  } = options;
  
  const allowedTypes = fileTypes[fileType] || fileTypes.any;
  
  const storage = createStorage(subDir);
  
  return multer({
    storage,
    fileFilter: allowedTypes.length ? fileFilter(allowedTypes) : undefined,
    limits: {
      fileSize: maxSize
    }
  }).array('files', maxCount);
};

// 分块上传处理
class ChunkUploadManager {
  constructor() {
    this.chunkMap = new Map(); // 存储分块信息
    this.chunkDir = path.join(BASE_UPLOAD_PATH, 'chunks');
    ensureUploadDirExists(this.chunkDir);
  }
  
  // 初始化分块上传会话
  initSession(fileInfo) {
    const { fileName, fileSize, totalChunks } = fileInfo;
    const sessionId = uuidv4();
    
    const sessionDir = path.join(this.chunkDir, sessionId);
    ensureUploadDirExists(sessionDir);
    
    this.chunkMap.set(sessionId, {
      fileName,
      fileSize,
      totalChunks,
      uploadedChunks: 0,
      chunkStatus: Array(parseInt(totalChunks)).fill(false),
      sessionDir,
      createdAt: Date.now()
    });
    
    return sessionId;
  }
  
  // 处理分块上传
  handleChunk(sessionId, chunkIndex, chunkFile) {
    const session = this.chunkMap.get(sessionId);
    
    if (!session) {
      throw new ApiError(404, '上传会话不存在');
    }
    
    const chunkPath = path.join(session.sessionDir, `chunk-${chunkIndex}`);
    fs.renameSync(chunkFile.path, chunkPath);
    
    session.chunkStatus[chunkIndex] = true;
    session.uploadedChunks += 1;
    
    // 检查是否所有分块已上传
    const isComplete = session.uploadedChunks === session.totalChunks;
    
    return { 
      sessionId, 
      chunkIndex, 
      isComplete,
      progress: Math.floor((session.uploadedChunks / session.totalChunks) * 100)
    };
  }
  
  // 合并分块
  async mergeChunks(sessionId, targetDir = 'merged') {
    const session = this.chunkMap.get(sessionId);
    
    if (!session) {
      throw new ApiError(404, '上传会话不存在');
    }
    
    if (session.uploadedChunks !== session.totalChunks) {
      throw new ApiError(400, '文件未完成上传');
    }
    
    const mergeDir = path.join(BASE_UPLOAD_PATH, targetDir);
    ensureUploadDirExists(mergeDir);
    
    const fileExt = path.extname(session.fileName);
    const mergedFilename = `${Date.now()}-${uuidv4()}${fileExt}`;
    const mergedFilePath = path.join(mergeDir, mergedFilename);
    
    const writeStream = fs.createWriteStream(mergedFilePath);
    
    // 按顺序合并所有分块
    for (let i = 0; i < session.totalChunks; i++) {
      const chunkPath = path.join(session.sessionDir, `chunk-${i}`);
      const chunkBuffer = await fs.promises.readFile(chunkPath);
      writeStream.write(chunkBuffer);
    }
    
    return new Promise((resolve, reject) => {
      writeStream.on('finish', () => {
        // 清理分块文件
        this.cleanupSession(sessionId);
        
        resolve({
          fileName: mergedFilename,
          originalName: session.fileName,
          size: session.fileSize,
          path: mergedFilePath,
          url: `/uploads/${targetDir}/${mergedFilename}`
        });
      });
      
      writeStream.on('error', (err) => {
        reject(new ApiError(500, '文件合并失败'));
      });
      
      writeStream.end();
    });
  }
  
  // 清理分块会话
  cleanupSession(sessionId) {
    const session = this.chunkMap.get(sessionId);
    
    if (session) {
      // 删除分块文件及目录
      try {
        fs.rmSync(session.sessionDir, { recursive: true, force: true });
      } catch (err) {
        console.error('清理分块文件失败:', err);
      }
      
      // 从Map中移除会话
      this.chunkMap.delete(sessionId);
    }
  }
  
  // 定期清理过期的分块会话（24小时后）
  startCleanupSchedule() {
    setInterval(() => {
      const now = Date.now();
      for (const [sessionId, session] of this.chunkMap.entries()) {
        // 24小时过期时间
        if (now - session.createdAt > 24 * 60 * 60 * 1000) {
          this.cleanupSession(sessionId);
        }
      }
    }, 60 * 60 * 1000); // 每小时检查一次
  }
}

// 创建分块上传管理器实例
const chunkManager = new ChunkUploadManager();
chunkManager.startCleanupSchedule();

// 上传服务
const UploadService = {
  // 图片上传（如头像等）
  imageUploader: createUploader({ 
    subDir: 'images', 
    fileType: 'images',
    maxSize: fileSizeLimits.avatar
  }),
  
  // 文档上传
  documentUploader: createUploader({
    subDir: 'documents',
    fileType: 'documents',
    maxSize: fileSizeLimits.document,
    maxCount: 5 // 支持批量上传
  }),
  
  // 视频上传
  videoUploader: createUploader({
    subDir: 'videos',
    fileType: 'videos',
    maxSize: fileSizeLimits.media
  }),
  
  // 音频上传
  audioUploader: createUploader({
    subDir: 'audio',
    fileType: 'audio',
    maxSize: fileSizeLimits.media
  }),
  
  // 通用文件上传
  generalUploader: createUploader({
    subDir: 'general',
    maxCount: 10
  }),
  
  // 分块上传处理器
  chunkUploader: multer({
    dest: path.join(BASE_UPLOAD_PATH, 'temp'),
    limits: { fileSize: fileSizeLimits.chunk }
  }).single('chunk'),
  
  // 获取分块上传管理器
  getChunkManager: () => chunkManager
};

export default UploadService;
